package com.hifar.aop;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hifar.plat.baseModal.service.IBaseSysLogService;
import com.hifar.plat.util.IpUtils;
import com.hifar.sys.SystemLoginUser;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Aspect
@Component
public class LoggingAspect {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private IBaseSysLogService baseSysLogService;

    // 定义切点（根据实际包名修改）
    @Pointcut("execution(* com.hifar.debug..*.*(..)) " +
            "&& @within(org.springframework.web.bind.annotation.RestController) " +
            "&& !@annotation(com.hifar.aop.NoLog) " +      // 排除有 @NoLog 注解的方法
            "&& !@within(com.hifar.aop.NoLog)")             // 排除类上有 @NoLog 的类
    public void requestLog() {
    }

    // 记录请求信息
    @AfterReturning("requestLog()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return;
        }
        HttpServletRequest request = attributes.getRequest();

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        // 打印请求的基本信息
//        System.out.println("=== REQUEST DETAILS ===");
//        System.out.println("Request URL       : " + request.getRequestURL().toString());
//        System.out.println("Request URI       : " + request.getRequestURI());
//        System.out.println("Context Path      : " + request.getContextPath());
//        System.out.println("Servlet Path      : " + request.getServletPath());
//        System.out.println("HTTP Method       : " + request.getMethod());
//        System.out.println("Remote Address    : " + request.getRemoteAddr());
//        System.out.println("Remote Host       : " + request.getRemoteHost());
//        System.out.println("Remote Port       : " + request.getRemotePort());
//        System.out.println("Local Address     : " + request.getLocalAddr());
//        System.out.println("Local Name        : " + request.getLocalName());
//        System.out.println("Local Port        : " + request.getLocalPort());
//        System.out.println("Protocol          : " + request.getProtocol());
//        System.out.println("Scheme            : " + request.getScheme());
//        System.out.println("Server Name       : " + request.getServerName());
//        System.out.println("Server Port       : " + request.getServerPort());
//        System.out.println("Character Encoding: " + request.getCharacterEncoding());
//        System.out.println("Content Type      : " + request.getContentType());
//        System.out.println("Content Length    : " + request.getContentLengthLong());
        // 获取请求ip
        String ip = IpUtils.getIpAddress(request);
        // 获取方法上的 ApiOperation 注解
        String operationValue = null;
        if (method.isAnnotationPresent(ApiOperation.class)) {
            ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
            operationValue = apiOperation.value(); // 获取 value 值
//            System.out.println("【API Operation Value】: " + operationValue);
            // 请求头信息
//        System.out.println("=== REQUEST HEADERS ===");
//        Enumeration<String> headerNames = request.getHeaderNames();
//        while (headerNames.hasMoreElements()) {
//            String headerName = headerNames.nextElement();
//            String headerValue = request.getHeader(headerName);
//            System.out.println(headerName + " : " + headerValue);
//        }

            // 获取登录用户
            String userId = SystemLoginUser.userId;
            String username = SystemLoginUser.idName;
//        System.out.println("USER        : " + (username != null ? username : "anonymous"));

            // 打印请求体
            String body = getRequestBody(request);
            Long currentTime = System.currentTimeMillis();
            // 转换为 yyyy-MM-dd HH:mm:ss 格式
            String timeStr = LocalDateTime.ofInstant(Instant.ofEpochMilli(currentTime), ZoneId.systemDefault())
                    .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
//            System.out.println(timeStr);
            String content = String.format("用户【%s】在【%s】操作了【%s】功能，相关参数为【%s】", username, timeStr, operationValue, body);
            //写入syslog
            baseSysLogService.queryLogRecord(operationValue, content, userId, username, ip, true, body,
                    currentTime);
        }
    }

    private String getRequestBody(HttpServletRequest request) {
        try {
            // 判断 Content-Type 类型
            String contentType = request.getContentType();
            if (contentType == null) {
                contentType = "";
            }

            StringBuilder sb = new StringBuilder();
            BufferedReader reader = request.getReader();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            String bodyStr = sb.toString();

            if (bodyStr.isEmpty()) {
                return "";
            }

            if (contentType.contains("application/json")) {
                return parseJsonBody(bodyStr);
            } else if (contentType.contains("application/x-www-form-urlencoded")) {
                return parseFormBody(bodyStr);
            } else {
                return "<unsupported content-type: " + contentType + ">";
            }

        } catch (IOException e) {
            return "<error reading request body>";
        }
    }


    // 获取原始请求体（适用于 POST/PUT 等有 body 的请求）
    private String parseJsonBody(String bodyStr) throws JsonProcessingException {
        JsonNode jsonNode = objectMapper.readTree(bodyStr);
        List<String> keyValuePairs = new ArrayList<>();

        if (jsonNode.isObject()) {
            Iterator<Map.Entry<String, JsonNode>> fields = jsonNode.fields();
            while (fields.hasNext()) {
                Map.Entry<String, JsonNode> field = fields.next();
                String key = field.getKey();
                JsonNode valueNode = field.getValue();

                // 忽略 null 和空字符串
                if (valueNode.isNull() || (valueNode.isTextual() && valueNode.asText().isEmpty())) {
                    continue;
                }

                String valueStr;

                if (valueNode.isTextual()) {
                    valueStr = valueNode.asText();
                } else if (valueNode.isArray()) {
                    // 处理数组类型，转为字符串表示
                    valueStr = valueNode.toString(); // 如: ["a", "b"]
                } else {
                    valueStr = valueNode.toString(); // number、boolean 等
                }

                keyValuePairs.add(key + "=" + valueStr);
            }
        } else if (jsonNode.isArray()) {
            // 处理纯数组情况（如 [1, 2, 3] 或 []）
            if (jsonNode.isEmpty()) {
                return "<empty array>";
            }
            keyValuePairs.add("array=" + jsonNode.toString());
        } else {
            // 其他类型直接返回原始值
            return bodyStr;
        }

        return String.join(", ", keyValuePairs);
    }

    private String parseFormBody(String bodyStr) {
        List<String> keyValuePairs = new ArrayList<>();
        String[] pairs = bodyStr.split("&");

        for (String pair : pairs) {
            if (pair.isEmpty()) continue;

            String[] keyValue = pair.split("=", 2);
            String key = urlDecode(keyValue[0]);
            String value = keyValue.length > 1 ? urlDecode(keyValue[1]) : "";

            // 忽略空值
            if (!value.isEmpty()) {
                keyValuePairs.add(key + "=" + value);
            }
        }

        return String.join(", ", keyValuePairs);
    }

    private String urlDecode(String str) {
        try {
            return URLDecoder.decode(str, StandardCharsets.UTF_8.name());
        } catch (Exception e) {
            return str;
        }
    }


}
